#pragma once
#ifndef SM2_H
#define SM2_H
// #include<stdint.h>
#include "stdint.h"
#include "pointoperation.h"
// 定义点
typedef struct Param
{
	mpz_t p; // 模数
	mpz_t a; // 一次项系数
	mpz_t b; // 常数项
	mpz_t n; // 阶
} param[1], *param_ptr;

// 参数初始化和释放
/**
 * 参数的初始化.
 */
void sm2_param_init(param sm2_param);

/**
 * 参数空间的释放.
 */
void sm2_param_clear(param sm2_param);

// 1.密钥生成
/**
 * 使用私钥生成公钥.
 */
void public_key_gen(point public_key, mpz_t private_key, param sm2_param, point base_point);

// 2.SM2签名函数
/**
 * @brief SM2签名函数
 *
 * @param sign 签名值
 * @param sign_len 签名值长度
 * @param sm2_param SM2参数
 * @param base_point G
 * @param private_key 私钥
 * @param base_info 基本信息。Z_A
 * @param base_info_len 基本信息的长度
 * @param msg 消息
 * @param msg_len 消息的长度
 */
void sm2_sign(uint8_t *sign, size_t sign_len, param sm2_param, point base_point, mpz_t private_key, uint8_t *base_info, size_t base_info_len, uint8_t *msg, size_t msg_len);

// 3.SM3验签函数
/**
 * @brief SM2签名函数
 *
 * @param sm2_param SM2参数
 * @param base_point 基点G
 * @param public_key 公钥
 * @param base_info 基本信息（接收到的信息）
 * @param base_info_len 基本信息长度
 * @param msg 消息（接收到的消息）
 * @param msg_len 消息的长度
 * @param sign 签名值
 * @param sign_len 签名值长度
 * @return int 返回1表示验签成功，返回其他值表示验签失败
 */
int sm2_verify_sign(param sm2_param, point base_point, point public_key, uint8_t *base_info, size_t base_info_len, uint8_t *msg, size_t msg_len, uint8_t *sign, size_t sign_len);

// 4.其他函数

void mpz_to_byte_array(unsigned char *byte_array, size_t size, mpz_t value);

// 拼接基本信息
void concat_base_info(uint8_t *out, size_t out_len, size_t ent_len, uint8_t *id, size_t id_len, param sm2_param, point base_point, point public_key);

void hash(uint8_t *out, uint8_t *msg, size_t msg_len);
/**
 * 将mpz转换为固定位数的字符串.
 *
 * \param num mpz格式的数
 * \param length 输出的字符串的长度
 * \param base 基数
 * \return
 */
void mpz_to_fixed_length_str(char *padded_str, size_t padded_str_len, mpz_t num, int base);

#endif
